#include "catalog.h"
#include "query.h"
#include "sort.h"
#include "index.h"
#include "error.h"
#define MAX(a,b) ((a) > (b) ? (a) : (b))

/*
 * Joins two relations.
 *
 * Returns:
 * 	OK on success
 * 	an error code otherwise
 */
Status Operators::Join(const string & result,      // name of the output relation 
                       const int projCnt,          // number of attributes in the projection
	               const attrInfo projNames[], // the list of projection attributes
	               const attrInfo *attr1,      // left attr in the join predicate
	               const Operator op,          // the predicate operation 
	               const attrInfo *attr2)     // right attr in the join predicate
{
    //need to decide which join to use
    Status ret;
    AttrDesc joinPred1, joinPred2;
    AttrDesc projDesc[projCnt];
    int totalLen = 0;

    ret = attrCat->getInfo(attr1->relName, attr1->attrName, joinPred1);
    if (ret != OK) return ret;
    ret = attrCat->getInfo(attr2->relName, attr2->attrName, joinPred2);
    if (ret != OK) return ret;

    //there should be something to return here...
    if (joinPred1.attrType != joinPred2.attrType) return ATTRTYPEMISMATCH;

    for(int i = 0; i < projCnt; i++)
    {
        ret = attrCat->getInfo(projNames[i].relName, projNames[i].attrName, projDesc[i]);
        if (ret != OK) return ret;
        totalLen += projDesc[i].attrLen;
    }

   if (op != EQ) 
       return SNL(result, projCnt, projDesc, joinPred1, op, joinPred2, totalLen); 
   else if (joinPred1.indexed || joinPred2.indexed) 
       return INL(result, projCnt, projDesc, joinPred1, op, joinPred2, totalLen); 
   else  
       return SMJ(result, projCnt, projDesc, joinPred1, op, joinPred2, totalLen); 
}
